/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;

import org.zhiqim.kernel.config.Config;
import org.zhiqim.kernel.constants.CodeConstants;
import org.zhiqim.kernel.constants.SignConstants;
import org.zhiqim.kernel.constants.ZhiqimConstants;
import org.zhiqim.kernel.model.maps.HashMapSS;
import org.zhiqim.kernel.util.Closes;
import org.zhiqim.kernel.util.Files;
import org.zhiqim.kernel.util.Streams;

/**
 * 知启蒙工程命令类，向监听类发起命令请求
 * 
 * 1. -s表示启动
 * 2. -c表示工程退出
 * 3. -i表示查看信息
 * 4. -t表示测试配置文件（TODO 暂未实现）
 * 5. -r表示重新加载配置（TODO 暂未实现）
 * 6. -h表示帮助
 * 7. -?表示帮助
 * 
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
final class ZhiqimCommand implements ZhiqimConstants, SignConstants, CodeConstants
{
    /** 不允许实例化 */
    private ZhiqimCommand(){};
    
    /** 命令集 */
    private static final HashMapSS commandMap = new HashMapSS();
    static
    {
        commandMap.put(Z_START_A,       Z_START_C);
        commandMap.put(Z_CLOSE_A,       Z_CLOSE_C);
        commandMap.put(Z_INFO_A,        Z_INFO_C);
        commandMap.put(Z_TEST_A,        Z_TEST_C);
        commandMap.put(Z_RELOAD_A,      Z_RELOAD_C);
        commandMap.put(Z_LOADER_A,      Z_LORDER_C);
        commandMap.put(Z_HELP_A,        Z_HELP_C);
        commandMap.put(Z_QUESTION_A,    Z_QUESTION_C);
    }
    
    /** 命令入口 */
    static void command(String[] args)
    {
        String cmd = commandMap.get(args[0]);
        if (cmd == null)
        {
            System.out.println("配置错误:\r\n不支持的参数，请使用-h查看支持的参数\r\n");
            System.exit(0);
            return;
        }
        
        String path = null;
        if (Files.exists(Z_CONF_ZHIQIM_XML))
            path = Z_CONF_ZHIQIM_XML;
        else if (Files.exists(Z_CONF_ZHIQIM_INI))
            path = Z_CONF_ZHIQIM_INI;
        
        if (path == null)
        {
            System.out.println("配置错误:\r\n配置文件[./conf/zhiqim.xml]和[./conf/zhiqim.ini]都不存在，请按手册配置目录结构\r\n");
            System.exit(0);
            return;
        }
        
        Socket s = null;
        
        try
        {
            Config config = new Config(Z_NAME, Z_CONF_ZHIQIM_XML);
            config.load();
            
            int port = config.getInt(Z_BOOT, Z_ITEM_PORT);
            if (port < 1 || port > 65535)
            {
                System.out.println("配置错误:\r\n配置文件["+path+"]端口不正确\r\n");
                System.exit(0);
                return;
            }

            String str = Z_NAME + _BR_ + cmd + _BR_;
            if (Z_LORDER_C.equals(cmd))
            {
                if (args.length != 2)
                {
                    System.out.println("命令错误:\r\n命令["+cmd+"]没有传入[serviceId]\r\n");
                    System.exit(0);
                    return;
                }
                String serviceId = args[1];
                if (config.hasItem(Z_SERVICE_LOADER, serviceId))
                {
                    System.out.println("配置错误:\r\n服务["+serviceId+"]不存在或未配置[loader]\r\n");
                    System.exit(0);
                    return;
                }
                
                str += serviceId + _BR_;
            }
            
            s = new Socket(InetAddress.getByName(_127_0_0_1_), port);
            OutputStream out = s.getOutputStream();
            out.write(str.getBytes());
            out.flush();
            
            if (Z_START_C.equals(cmd) || Z_CLOSE_C.equals(cmd))
            {//启动和关闭无需消息
                s.shutdownOutput();
            }
            else
            {//其他的等待消息
                InputStream in = s.getInputStream();
                String result = Streams.getStringUTF8(in);
                System.out.println(result);
            }
        }
        catch (ConnectException e) 
        {
            System.out.println("连接失败:\r\n工程可能未启动\r\n");
        }
        catch (Throwable e)
        {
            e.printStackTrace();
        }
        finally
        {
            Closes.closeIgnoreException(s);
            System.exit(0);
        }
    }
}
